<template>
	<a-select
		ref="zhSelectRef"
		v-model:value="value"
		v-bind="attrs"
		:id="'zhSelect' + columnId"
		:name="'zhSelect' + columnId"
		:size="mySize"
		:fieldNames="fieldNames"
		style="width: 100%"
		:showSearch="showSearch"
		:options="myOptions"
		:allowClear="allowClear"
		:placeholder="placeholder"
		:filter-option="myFilterOption"
		:notFoundContent="notFoundContent"
		@popupScroll="onPopupScroll"
		@search="handleSearch"
		@dropdownVisibleChange="onDropdownVisibleChange"
	>
		<template #[item]="data" v-for="item in Object.keys($slots)">
			<slot :name="item" v-bind="data || {}"></slot>
		</template>
	</a-select>
</template>
<script lang="ts" setup name="zh-select">
import { itemProps } from '@/components/lib/base/props-item';
import itemController from '@/components/lib/base/controller-item';
import { theme } from '@/store';
import { toLine, deepClone } from '@/utils/util';
import { useRequest } from 'vue-request';
//------------------接收传入参数(组件)-------------------
const props = defineProps({
	...itemProps, // 基础属性
	fieldNames: {
		type: Object,
		default: () => {
			return { label: 'dictValue', value: 'dictKey', options: 'children' };
		},
	},
	options: {
		type: Array,
		default: () => {
			return [];
		},
	},
	modelValue: {
		type: [Number, String, Boolean, Array],
		default: undefined,
	},
	//	使单选模式可搜索
	showSearch: {
		type: Boolean,
		default: true,
	},
	//是否允许用户创建新条目(暂未实现)
	allowCreate: {
		type: Boolean,
		default: true,
	},
	filterOption: {
		type: [Function, Boolean],
	},
	lazy: {
		type: Boolean,
		default: false,
	},
	notFoundContent: {
		type: String,
		default: '没有可选择的数据',
	},
	//查询附带参数
	searchParams: {
		type: Object,
		default() {
			return {
				tableName: 'sys_dict',
				resultList: [],
				queryList: [],
				pageNum: 1,
				pageSize: 20,
			};
		},
	},
	defaultFlag: {
		type: Boolean,
		default: false,
	},
	//查询url
	url: {
		type: String,
		default() {
			return '';
		},
	},
	//查询功能编号
	funcCode: {
		type: String,
		default() {
			return '';
		},
	},
	//查询主字段名称
	searchField: {
		type: String,
		default() {
			return '';
		},
	},
	placeholder: {
		type: String,
		default: '请选择',
	},
	allowClear: {
		type: Boolean,
		default: true,
	},
	//是否加密
	cryptoEnabled: {
		type: Boolean,
		default: false,
	},
	//是否脱敏
	desensitizeFlag: {
		type: Boolean,
		default: false,
	},
	//是否防重复提交
	repeatEnabled: {
		type: Boolean,
		default: false,
	},
	//接口超时时间
	timeout: Number,
});
const attrs = useAttrs();
const emit = defineEmits(['update:modelValue']);
const allAttrs = computed(() => {
	return Object.assign(props.extend, attrs);
});

//------------------定义子组件---------------------------

//------------------内部变量定义-------------------------
const { value, globalSize } = itemController(props, allAttrs.value, emit);
const state = reactive({
	mySize: allAttrs.value.size || theme.globalComponentSize,
	searchText: '', //搜索框内容
	hasNextPage: true, //是否还有分页数据
	myLoading: false,
});
const myOptions = ref<any>(props.options || []);
if(props.defaultFlag&&!value.value&&myOptions.value.length>0){
	value.value=myOptions.value[0][nodeValue.value]
}
const mySearchParams = ref<any>(
	Object.assign(props.searchParams, {
		tableName: 'sys_dict',
		resultList: [],
		queryList: [],
		pageNum: 1,
		pageSize: 50,
	})
);
const nodeLabel = computed(() => {
	if (props.fieldNames.bindLabel) {
		return props.fieldNames.bindLabel;
	}
	return props.fieldNames.label;
});
const nodeValue = computed(() => {
	if (props.fieldNames.bindValue) {
		return props.fieldNames.bindValue;
	}
	return props.fieldNames.value;
});
//------------------定义调用方法-------------------------
globalSize(state);

const myFilterOption = (inputValue: string, option: any) => {
	if (props.lazy) {
		return true;
	}
	if (props.filterOption) {
		return props.filterNodeMethod(inputValue, option);
	} else {
		if (!inputValue) return true;
		if (!option[props.fieldNames.label]) return true;
		return option[props.fieldNames.label].toLowerCase().indexOf(inputValue.toLowerCase()) >= 0;
	}
};

const onPopupScroll = (e) => {
	if (!props.lazy) {
		return;
	}
	const { target } = e;
	// target.scrollTop + target.offsetHeight === target.scrollHeight  判断是否滑动到底部
	if (target.scrollTop + target.offsetHeight === target.scrollHeight) {
		// 在这里调用接口
		handleSearch(state.searchText);
	}
};

let onSearch = () => {
	return new Promise((resolve) => {
		if (!mySearchParams.value.tableName) {
			mySearchParams.value.tableName = 'sys_dict';
		}
		let searchField = props.searchField;
		if (!searchField) {
			searchField = toLine(nodeLabel.value);
		}
		mySearchParams.value.keyName = nodeLabel.value;
		mySearchParams.value.valueName = nodeValue.value;
		mySearchParams.value.searchField = searchField;
		mySearchParams.value.searchText = state.searchText;
		mySearchParams.value[props.searchField] = state.searchText;

		let config: any = {};
		if (props.timeout && props.timeout > 0) {
			config.timeout = props.timeout;
		}
		let searchUrl = $api.common.getDictSearchData.url;
		let headers = {} as any;
		headers.cryptoEnabled = props.cryptoEnabled;
		headers.repeatEnabled = props.repeatEnabled;
		headers.desensitizeFlag = props.desensitizeFlag;
		if (props.funcCode) {
			headers['func-code'] = props.funcCode;
			searchUrl = $api.common.send.url + props.funcCode;
		} else {
			if (props.url) {
				searchUrl = props.url;
			}
		}
		config.headers = headers;
		$http
			.post(searchUrl, mySearchParams.value, config)
			.then((res: any) => {
				if (mySearchParams.value.pageNum === 1) {
					myOptions.value = res.result.list || [];
				} else {
					myOptions.value = myOptions.value.concat(res.result.list || []);
				}
				if(props.defaultFlag&&!value.value&&myOptions.value.length>0){
					value.value=myOptions.value[0][nodeValue.value]
				}
				mySearchParams.value.pageNum = mySearchParams.value.pageNum + 1;
				state.hasNextPage = res.result.hasNextPage;
				resolve(true);
			})
			.catch(() => {
				resolve(false);
			});
	});
};
const { run: searchRun, loading: searchLoading } = useRequest(onSearch, {
	manual: true,
	debounceInterval: 1000,
	debounceOptions: {
		leading: false,
		maxWait: undefined,
		trailing: true,
	},
});
const handleSearch = (val: string) => {
	if (props.lazy) {
		if (state.searchText !== val) {
			mySearchParams.value.pageNum = 1;
			state.hasNextPage = true;
		}
		if (!state.hasNextPage) {
			return;
		}
		state.searchText = val;
		searchRun();
	}
};
//初始化数据
const initSelectMethod = () => {
	if (!props.lazy) {
		return;
	}
	if (!value.value&&!props.defaultFlag) {
		return;
	}
	let searchFlag=true;
	if(myOptions.value&&myOptions.value.length>0){
		if (allAttrs.value.mode === 'multiple') {
			let idList = null;
			if (props.modelValue) {
				idList = props.modelValue;
			}
			idList.forEach(valStr => {
				let idFlag=true;
				myOptions.value.forEach(element => {
					if(element[nodeValue.value]===valStr){
						idFlag=false;
					}
				});
				if(idFlag){
					searchFlag=false;
				}
			});
		} else {
			myOptions.value.forEach(element => {
				if(element[nodeValue.value]===value.value){
					searchFlag=false;
				}
			});
		}
	}
	if(!searchFlag){
		return;
	}
	let params = deepClone(mySearchParams.value);
	if (!params.tableName) {
		params.tableName = 'sys_dict';
	}
	let searchField = props.searchField;
	if (!searchField) {
		searchField = toLine(nodeLabel.value);
	}

	params.keyName = nodeLabel.value;
	params.valueName = nodeValue.value;
	params.searchField = searchField;
	if (props.modelValue) {
		if (typeof props.modelValue === 'number' || typeof props.modelValue === 'boolean' || props.modelValue.length > 0) {
			params.queryList.push({
				fieldName: toLine(nodeValue.value),
				fieldValue: props.modelValue,
			});
		}
	}
	if (allAttrs.value.mode === 'multiple') {
		let idList = null;
		if (props.modelValue) {
			idList = props.modelValue;
		}
		params[nodeValue.value + 'List'] = idList;
	} else {
		params[nodeValue.value] = props.modelValue;
	}
	let searchUrl = $api.common.getDictSearchData.url;
	let config: any = {};
	if (props.timeout && props.timeout > 0) {
		config.timeout = props.timeout;
	}
	let headers = {} as any;
	headers.cryptoEnabled = props.cryptoEnabled;
	headers.repeatEnabled = props.repeatEnabled;
	headers.desensitizeFlag = props.desensitizeFlag;
	if (props.funcCode) {
		headers['func-code'] = props.funcCode;
		searchUrl = $api.common.send.url + props.funcCode;
	} else {
		if (props.url) {
			searchUrl = props.url;
		}
	}
	config.headers = headers;
	$http.post(searchUrl, params, config).then((res: any) => {
		myOptions.value = res.result.list || [];
		if(props.defaultFlag&&!value.value&&myOptions.value.length>0){
			value.value=myOptions.value[0][nodeValue.value]
		}
		state.hasNextPage = res.result.hasNextPage;
	});
};
const onDropdownVisibleChange = (open) => {
	if (props.lazy) {
		if (open) {
			mySearchParams.value.pageNum = 1;
			state.searchText = '';
			onSearch();
		} else {
			state.searchText = '';
		}
	}
};
//------------------监听--------------------------------
watch(
	() => props.options,
	(val) => {
		myOptions.value = val || [];
		if(props.defaultFlag&&!value.value&&myOptions.value.length>0){
			value.value=myOptions.value[0][nodeValue.value]
		}
	},
	{
		immediate: true,
	}
);
watch(
	() => searchLoading.value,
	(val) => {
		state.myLoading = val;
	}
);
watch(
	() => props.modelValue,
	() => {
		nextTick(() => {
			initSelectMethod();
		});
	}
);
watch(
	() => props.searchParams,
	() => {
		mySearchParams.value=Object.assign(mySearchParams.value,props.searchParams)
		onSearch()
	}
);
//------------------初始化------------------------------
onMounted(() => {
	nextTick(() => {
		if(props.lazy){
			if(props.modelValue||props.defaultFlag){
				initSelectMethod();
			}
			
		}
	});
});
//------------设置给父组件调用的数据/方法(组件)-----------
// 输出
const { mySize } = toRefs(state);
</script>
<style lang="scss">
.ant-select {
	color: var(--el-text-color-regular);
}
.ant-select-multiple .ant-select-selection-item {
	border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
	background: var(--next-bg-color);
	color: var(--el-text-color-regular);
	border: 1px solid var(--next-bg-color);
}
.ant-select-multiple .ant-select-selection-item-remove {
	color: var(--el-text-color-regular);
}
.ant-select:not(.ant-select-disabled):hover .ant-select-selector {
	border: 0px solid var(--el-input-border-color, var(--el-border-color));
	box-shadow: 0 0 0 1px var(--el-border-color-hover) inset;
	border-right-width: 0px !important;
}
.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
	border: 0px solid var(--el-input-border-color, var(--el-border-color));
	box-shadow: 0 0 0 1px var(--el-color-primary) inset;
	border-right-width: 0px !important;
}
.ant-select:not(.ant-select-customize-input) .ant-select-selector {
	position: relative;
	background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
	border: 1px solid var(--el-input-border-color, var(--el-border-color));
	border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
	transition: none;
	outline: none !important;
}
.ant-select-dropdown {
	color: var(--el-text-color-regular);
	z-index: 2999;
	background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
	box-shadow: 0 3px 6px -4px var(--el-border-color-hover), 0 6px 16px 0 var(--el-border-color-hover), 0 9px 28px 8px var(--el-border-color-hover);
}
.ant-select-item {
	color: var(--el-text-color-regular);
}
.ant-select-item-group {
	color: var(--el-color-primary-light-7);
}
.ant-select-item-option-active:not(.ant-select-item-option-disabled) {
	background-color: #f5f5f5;
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
	color: var(--el-color-primary);
	font-weight: 600;
	background-color: var(--el-color-primary-light-9);
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) .ant-select-item-option-state {
	color: var(--el-color-primary);
}
.ant-select-disabled.ant-select-multiple .ant-select-selector {
	background: var(--el-disabled-bg-color);
	cursor: not-allowed;
}
.ant-select-disabled.ant-select-multiple .ant-select-selection-item {
	color: var(--el-disabled-text-color);
	border-color: var(--el-disabled-bg-color);
	cursor: not-allowed;
}
.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector {
	color: var(--el-text-color-regular);
	background: var(--el-disabled-bg-color);
	cursor: not-allowed;
}
.ant-select-multiple.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector {
	background: var(--el-disabled-bg-color);
}
.ant-select-clear {
	color: var(--el-text-color-regular);
	background: var(--next-bg-color);
}
.ant-select-selection-placeholder {
	color: var(--el-text-color-placeholder);
}
</style>
